package com.cloud.xtools.user.service.admin.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cloud.xtools.common.exception.ServiceException;
import com.cloud.xtools.common.redis.RedisService;
import com.cloud.xtools.user.domain.entity.User;
import com.cloud.xtools.user.domain.request.admin.UserLoginRequest;
import com.cloud.xtools.user.domain.request.admin.UserRegisterRequest;
import com.cloud.xtools.user.domain.resource.TokenResource;
import com.cloud.xtools.user.domain.resource.admin.UserResource;
import com.cloud.xtools.user.mapper.UserMapper;
import com.cloud.xtools.user.service.admin.AuthService;
import com.cloud.xtools.common.util.Auth;
import com.cloud.xtools.common.util.JwtUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;


/**
 * @author Daixinguo
 */
@Service
@RequiredArgsConstructor
public class AuthServiceImpl extends ServiceImpl<UserMapper, User> implements AuthService {

    @Value("${jwt.expiration}")
    private long expirationTime;

    // 自动装配 BCryptPasswordEncoder
    private final PasswordEncoder passwordEncoder;

    private final JwtUtil jwtUtil;

    private final RedisService redisService;

    @Override
    public UserResource register(UserRegisterRequest userRegisterRequest) {
        // 1、设置为管理员
        userRegisterRequest.setAdmin(true);
        // 2、明文密码加密
        userRegisterRequest.setPassword(passwordEncoder.encode(userRegisterRequest.getPassword()));
        // 3、保存用户信息
        User user = BeanUtil.copyProperties(userRegisterRequest, User.class);
        save(user);

        return BeanUtil.copyProperties(user, UserResource.class);
    }

    @Override
    public TokenResource login(UserLoginRequest userLoginRequest) {
        // 查询用户
        User user = getOne(new QueryWrapper<>(User.class)
                .eq("username", userLoginRequest.getUsername())
                .or()
                .eq("email", userLoginRequest.getUsername())
                .or()
                .eq("mobile", userLoginRequest.getUsername())
        );
        // System.out.println("#####");
        // System.out.println(user);
        if (user == null || !passwordEncoder.matches(userLoginRequest.getPassword(), user.getPassword())) {
            throw new ServiceException("用户名或密码错误");
        }

        final var token = jwtUtil.createToken(user.getId(), user.getUsername());
        // System.out.println(token);
        // // 是否有效
        // System.out.println(jwtUtil.validateToken(token, userLoginRequest.getUsername()));
        // 是否过期
        // System.out.println(jwtUtil.isTokenExpired(token));
        // // 解析出来的数据
        // System.out.println("******");
        // System.out.println(jwtUtil.extractAllClaims(token));
        // System.out.println(jwtUtil.extractId(token));
        // // 过期时间
        String expiresAt = DateUtil.parse(jwtUtil.extractExpiration(token).toString()).toString();
        // System.out.println(DateUtil.parse(jwtUtil.extractExpiration(token).toString()));

        // 将 token 保存在 redis 中，在 redis 中的表示为白名单用户，当用户退出登录、或者拉黑用户时删除 redis 中保存的 token
        // jwt 的 id 作为 key，用户 id 作为值
        redisService.setString(jwtUtil.extractId(token), user.getId(), expirationTime / 1000);

        return new TokenResource(token, expiresAt);
    }

    @Override
    public void logout() {
        String token = Auth.getRequest().getHeader("Authorization");
        redisService.delete(jwtUtil.extractId(token));
    }
}
